package net.fxug.hokuriku.chocolat.view
{
    import flash.display.NativeWindow;
    import flash.display.NativeWindowInitOptions;
    import flash.display.NativeWindowSystemChrome;
    import flash.display.NativeWindowType;
    import flash.display.Screen;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    import flash.text.TextFormat;
    import flash.utils.Dictionary;

    import net.fxug.hokuriku.chocolat.events.SessionTimerEvent;
    import net.fxug.hokuriku.chocolat.events.VoteEvent;
    import net.fxug.hokuriku.chocolat.events.VoteStatusEvent;
    import net.fxug.hokuriku.chocolat.helper.TimeFormatter;
    import net.fxug.hokuriku.chocolat.model.SessionTimer;
    import net.fxug.hokuriku.chocolat.model.VoteData;
    import net.fxug.hokuriku.chocolat.model.VoteInfo;
    import net.fxug.hokuriku.chocolat.service.VoteManager;
    import net.fxug.hokuriku.chocolat.utils.EventUtil;

    /**
     * タイマーのタイムライン表示クラス
     * タイムアップ、またはタイムラインをダブルクリックすると閉じる
     *
     * @author shoito
     */
    public class TimelineTimer extends NativeWindow
    {
        private static const WINDOW_HEIGHT:Number = 84;
        private static const BAR_HEIGHT:Number = 20;
        private static const BAR_ROUND:Number = 5;
        private static const BASETIME_COLOR:uint = 0x0000ff;
        private static const BONUSTIME_COLOR:uint = 0x00ff00;
        private static const GUTTER:Number = 10;
        private static const ALARM_TIME:int = 15;

        private var remainingTimeFormat:TextFormat = new TextFormat(null, 48, 0xff0000, true);
        private var periodFormat:TextFormat = new TextFormat(null, 16, 0x333333, true);

        private var sessionTimer:SessionTimer;

        private var timeline:Sprite;
        private var remainingTime:TextField;
        private var period:TextField;

        /** 通知上限に達したユーザ情報のMap */
        private var limitUserMap:Dictionary = new Dictionary();

        public function TimelineTimer()
        {
            this.sessionTimer = SessionTimer.getInstance();

            var options:NativeWindowInitOptions = new NativeWindowInitOptions();
            options.type = NativeWindowType.LIGHTWEIGHT;
            options.systemChrome = NativeWindowSystemChrome.NONE;
            options.transparent = true;
            super(options);

            initializeContents();
        }

        private function initializeContents():void
        {
            this.stage.align = StageAlign.TOP_LEFT;
            this.stage.scaleMode = StageScaleMode.NO_SCALE;

            this.alwaysInFront = true;
            this.width = Screen.mainScreen.bounds.width;
            this.height = WINDOW_HEIGHT; //BAR_HEIGHT;
            this.x = 0;
            this.y = Screen.mainScreen.bounds.height - WINDOW_HEIGHT; //BAR_HEIGHT;

            this.timeline = new Sprite();
            this.timeline.doubleClickEnabled = true;
            this.timeline.addEventListener(MouseEvent.DOUBLE_CLICK, doubleClickHandler);
            this.stage.addChild(timeline);
            this.timeline.x = 0;
            this.timeline.y = WINDOW_HEIGHT - BAR_HEIGHT;

            remainingTime = new TextField();
            this.stage.addChild(remainingTime);

            var timeFormatter:TimeFormatter = new TimeFormatter(true);
            period = new TextField();
            period.text = timeFormatter.format(sessionTimer.period);
            period.setTextFormat(periodFormat);
            this.stage.addChild(period);
            period.x = Screen.mainScreen.bounds.width - period.textWidth - GUTTER;
            period.y = WINDOW_HEIGHT - BAR_HEIGHT;

            this.sessionTimer.addEventListener(Event.CHANGE, sessionTimer_changeHandler);
            this.sessionTimer.addEventListener(SessionTimerEvent.TIME_UP, sessionTimer_timeUpHandler);

            drawTimeline();

            // タイムライン描画が完了した時点で、Popup通知領域のイベントを設定する。
            VoteManager.getInstance().addEventListener(VoteEvent.GOOD_EVENT, voteManager_voteEventHandler);
            VoteManager.getInstance().addEventListener(VoteEvent.BAD_EVENT, voteManager_voteEventHandler);
            VoteManager.getInstance().addEventListener(VoteStatusEvent.MAX_VOTE_EVENT, maxVoteEventHandler);
        }

        private function voteManager_voteEventHandler(voteEvent:VoteEvent):void
        {
            if (voteEvent.tweetArray == null || voteEvent.tweetArray.length == 0)
            {
                return;
            }
            var index:int = voteEvent.tweetArray.length;
            for (var i:int = 0; i < index; i++)
            {
                var voteData:VoteData = voteEvent.tweetArray[i];
                NotificationManager.getInstance().notify(EventUtil.fromVoteEventToNotifyManagerType(voteEvent), voteData.text, voteData.id, voteData.link);

                // つぶやき自体が無効の場合はタイムラインへの反映を行わない
                if (!voteData.voteEnabled)
                {
                    trace("This vote is not appre voteData::" + voteData);
                    continue;
                }
//                // 全体管理情報からリミット情報を確認
//                // FIXME ただしこの実装には以下の問題がある。
//                // Twitter検索時にまとめて検索結果がVoteされるため、上限値を一気に超えてしまうケースがある
//                // あとでまとめて手を入れるのでとりあえず、既知バグとして放置してください。 by hikaruworld
//                var info:VoteInfo = this.limitUserMap[voteData.id];
//                var isExec:Boolean = info == null ? true : info.isExecute(voteEvent.type);
//
//                trace("isExec::" + isExec + "::" + info);

//                if (isExec)
//                {
//                }
                trace("APPER TIMELINE::" + voteData);
                var gravity:int = (voteEvent.type == VoteEvent.GOOD_EVENT) ? 5 * 1000 : -3 * 1000;
                sessionTimer.adjustBonus(gravity);
            }
        }

        private function maxVoteEventHandler(voteStatuEvent:VoteStatusEvent):void
        {
            var voteInfo:VoteInfo = voteStatuEvent.value as VoteInfo;
            this.limitUserMap[voteInfo.userId] = voteInfo;
        }

        private function drawTimeline():void
        {
            if (sessionTimer.period <= 0)
            {
                return;
            }

            var basetimePerPeriod:Number = sessionTimer.basetime / sessionTimer.period;
            var bonusPerPeriod:Number = ((sessionTimer.remainingTime > sessionTimer.adjustedBonus) ? sessionTimer.adjustedBonus : sessionTimer.remainingTime) / sessionTimer.period;

            var bonusWidth:Number = Screen.mainScreen.bounds.width * bonusPerPeriod;
            var basetimeWidth:Number = Screen.mainScreen.bounds.width * basetimePerPeriod;
            basetimeWidth = (basetimeWidth > 0) ? basetimeWidth : 0;

            this.timeline.graphics.clear();
            this.timeline.graphics.beginGradientFill("linear", [BONUSTIME_COLOR, BONUSTIME_COLOR], [1.0, 0.8], [0, 128]);
            this.timeline.graphics.drawRoundRect(0, 0, bonusWidth, BAR_HEIGHT, BAR_ROUND, BAR_ROUND);

            this.timeline.graphics.beginGradientFill("linear", [BASETIME_COLOR, BASETIME_COLOR], [1.0, 0.8], [0, 128]);
            this.timeline.graphics.drawRoundRect(bonusWidth, 0, basetimeWidth, BAR_HEIGHT, BAR_ROUND, BAR_ROUND);
        }

        private function drawRemainingTime():void
        {
            var seconds:int = sessionTimer.remainingTime / 1000;
            remainingTime.text = seconds.toString();
            remainingTime.setTextFormat(remainingTimeFormat);
            remainingTime.x = GUTTER;
            remainingTime.y = WINDOW_HEIGHT - remainingTime.textHeight - BAR_HEIGHT;
            remainingTime.width = remainingTime.textWidth + GUTTER;
            remainingTime.height = remainingTime.textHeight + GUTTER;
        }

        private function sessionTimer_changeHandler(event:Event):void
        {
            drawTimeline();

            var seconds:int = sessionTimer.remainingTime / 1000;
            if (seconds <= ALARM_TIME)
            {
                drawRemainingTime();
            }
        }

        private function doubleClickHandler(event:MouseEvent):void
        {
            super.close();
        }

        private function sessionTimer_timeUpHandler(event:Event):void
        {
            super.close();
        }
    }
}